package com.wsjc.common.solr;

import java.net.URLDecoder;
import java.util.Collection;
import java.util.List;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.wsjc.common.core.config.SolrConfig;
import com.wsjc.common.solr.factory.SolrServerFactory;

@Service
public class SolrClientUtils<T> {

	private static Logger logger = LoggerFactory.getLogger(SolrClientUtils.class);

	private static SolrServerFactory solrServerFactory;

	private static SolrServer solrServer;

	static {
		try {
			solrServerFactory = SolrServerFactory.getInstance() ;
			/** 获取节点连接 **/
			solrServer = solrServerFactory.getSolrServerInstance(SolrConfig.readConfig("solr.client.type"));
			logger.debug("Solr-DEBUG|SolrClientUtils|debug: SolrServer 初始化成功!");
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils|error: SolrServer 初始化失败!", e);
		}

	}

	/*
	 * 在apache-solr-3.4.0\example\solr\conf目录下的schema.xml中可以找到有关于field属性的配置，
	 * schema.xml中的field就和上面Document文档中的field（id、name、manu）对应。 如果出现ERROR:unknown
	 * field 'xxxx'就表示你设置的这个field在schema.xml中不存在。如果一定要使用这个field，请你在schema.
	 * xml中进行filed元素的配置。具体请参考前面的章节。
	 * 注意：在schema.xml中配置了uniqueKey为id，就表示id是唯一的。如果在添加Document的时候，id重复添加。
	 * 那么后面添加的相同id的doc会覆盖前面的doc， 类似于update更新操作，而不会出现重复的数据。
	 */

	/**
	 * 利用SolrJ完成Index Document的添加操作 <b>function:</b> 添加doc文档
	 * 
	 * @author 9373
	 * @createDate 2011-10-21 上午09:49:10
	 */
	public void addDoc(SolrInputDocument doc) throws RuntimeException {

		try {
			// 添加一个doc文档
			UpdateResponse response = solrServer.add(doc);
			solrServer.commit();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-addDoc()|Result:查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-addDoc()|操作失败", e);
		}
	}

	/**
	 * 利用SolrJ添加多个Document，即添加文档集合 就是添加一个List集合 <b>function:</b> 添加docs文档集合
	 * 
	 * @author 9373
	 * @createDate 2011-10-21 上午09:55:01
	 */
	public void addDocs(Collection<SolrInputDocument> docs) {

		try {
			// add docs
			UpdateResponse response = solrServer.add(docs);
			// commit后才保存到索引库
			solrServer.commit();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-addDocs()|Result:查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-addDocs()|操作失败", e);
		}
	}

	/*
	 * 注意上面的属性是和在apache-solr-3.4.0\example\solr\conf目录下的schema.
	 * xml中可以找到有关于field属性的配置对应的。如果你Index
	 * JavaBean中出现的属性在schema.xml的field配置无法找到，那么出出现unknown filed错误。
	 * 
	 * 添加Bean完成doc添加操作
	 */

	/**
	 * <b>function:</b> 添加JavaEntity Bean
	 * 
	 * @author 9373
	 * @createDate 2011-10-21 上午09:55:37
	 */
	public void addBean(Object bean) {

		try {
			// 添加Index Bean到索引库
			UpdateResponse response = solrServer.addBean(bean);
			// commit后才保存到索引库
			solrServer.commit();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-addBean()|Result:查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-addBean()|操作失败", e);
		}
	}

	/**
	 * 添加Bean集合 <b>function:</b> 添加Entity Bean集合到索引库
	 * 
	 * @author 9373
	 * @createDate 2011-10-21 上午10:00:55
	 */
	public void addBeans(List<T> beans) {

		try {
			// 添加索引库
			UpdateResponse response = solrServer.addBeans(beans);
			// commit后才保存到索引库
			solrServer.commit();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-addBeans()|Result:查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-addBeans()|操作失败", e);
		}
	}

	/**
	 * 删除索引Document 
	 * <b>function:</b> 删除索引操作
	 * 
	 * @author 9373
	 * @createDate 2011-10-21 上午10:04:28
	 */
	
	public void remove(String id) {
		
		try {
			// 删除id为1的索引
			solrServer.deleteById(id);
			// commit后才保存到索引库
			solrServer.commit();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-remove()|Result: 删除成功!  id=").append(id).toString()) ;
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-remove()|操作失败", e);
		}
	}
	
	public void remove(List<String> ids) {
		
		try {
			// 删除id为1的索引
			solrServer.deleteById(ids);
			// commit后才保存到索引库
			solrServer.commit();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-remove()|Result: 批量删除成功!  ids=").append(ids.toString()).toString()) ;
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-remove()|操作失败", e);
		}
	}

	/**
	 * 查询索引 
	 * <b>function:</b> 查询所有索引信息
	 * 
	 * @author 9373
	 * @createDate 2011-10-21 上午10:05:38
	 */
	
	public SolrDocumentList queryAllIndexdebug(ModifiableSolrParams params) {

		SolrDocumentList list = null ;
		try {
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-queryAllIndexdebug()|params: ").append(URLDecoder.decode(params.toString(), "utf-8")).toString());
			QueryResponse response = solrServer.query(params);
			list = response.getResults();
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-queryAllIndexdebug()|Result: 总个数->").append(list.size()).append(" 查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-queryAllIndexdebug()|操作失败", e);
		}
		return list ;
	}


	/**
	 * 文档查询 
	 * <b>function:</b> query 基本用法测试
	 * 
	 * @author 9373
	 * @createDate 2011-10-20 下午04:44:28
	 */
	public QueryResponse queryCase(SolrQuery params) {

		QueryResponse response = null ;
		try {
			response = solrServer.query(params);
			logger.debug(new StringBuilder(128).append("Solr-DEBUG|SolrClientUtils-queryCase()|Result: 查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
		} catch (Exception e) {
			logger.debug("Solr-ERROR|SolrClientUtils-queryCase()|操作失败", e);
		}
		return response ;
	}
	
	/**
	 * 分片查询、统计 
	 * <b>function:</b> 分片查询， 可以统计关键字及出现的次数、或是做自动补全提示
	 * 
	 * @author 9373
	 * @createDate 2011-10-20 下午04:54:25
	 */
	public int facetQueryCase(SolrQuery params) {

	
		// demo Facet为solr中的层次分类查询 分片信息
//		params.setFacet(true).setQuery("*:*").setFacetMinCount(1).setFacetLimit(5)// 段
//				// .setFacetPrefix("electronics", "cat")
//				.setFacetPrefix("cor")// 查询manu、name中关键字前缀是cor的
//				.addFacetField("manu").addFacetField("name");// 分片字段

		int total = 0 ;
		try {
			QueryResponse response = solrServer.query(params);
			// 输出分片信息
			List<FacetField> facets = response.getFacetFields();
			logger.debug(new StringBuilder(128).append("Solr-debug|SolrClientUtils-facetQueryCase()|Result:查询时间->").append(response.getQTime()).append(" 运行时间->").append(response.getElapsedTime()).append(" 状态->").append(response.getStatus()).toString());
			for (FacetField facet : facets) {
				logger.debug("Solr-DEBUG|SolrClientUtils-facetQueryCase()|FacetField name=" + facet.getName());
				List<Count> facetCounts = facet.getValues();
				for (FacetField.Count count : facetCounts) {
					total += count.getCount() ;
					// 关键字 - 出现次数
					logger.debug("Solr-DEBUG|SolrClientUtils-facetQueryCase()|FacetField.Count " + count.getName() + ": " + count.getCount() );
				}
			}
		} catch (Exception e) {
			logger.error("Solr-ERROR|SolrClientUtils-facetQueryCase()|操作失败", e);
		}
		return total ;
	}

}
